import pymysql
import json
import os
from typing import Any, List, Tuple, Dict, Optional

class MySQLUtil:
    def __init__(self, config_path: str = None):
        if config_path is None:
            config_path = os.path.join(os.path.dirname(__file__), 'db_config.json')
        self._load_config(config_path)
        self.conn = None
        self.connect()

    def _load_config(self, config_path: str):
        try:
            with open(config_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
            self.host = config.get('host', 'localhost')
            self.user = config.get('user', '')
            self.password = config.get('password', '')
            self.database = config.get('database', '')
            self.port = config.get('port', 3306)
            self.charset = config.get('charset', 'utf8mb4')
        except Exception as e:
            raise RuntimeError(f"读取数据库配置文件失败: {e}")

    def connect(self):
        try:
            self.conn = pymysql.connect(
                host=self.host,
                user=self.user,
                password=self.password,
                database=self.database,
                port=self.port,
                charset=self.charset,
                cursorclass=pymysql.cursors.DictCursor
            )
        except Exception as e:
            print(f"连接数据库失败: {e}")
            self.conn = None

    def close(self):
        if self.conn:
            self.conn.close()
            self.conn = None

    def execute(self, sql: str, params: Optional[Tuple[Any, ...]] = None) -> int:
        """执行插入、更新、删除操作，返回受影响的行数"""
        try:
            with self.conn.cursor() as cursor:
                cursor.execute(sql, params)
                self.conn.commit()
                return cursor.rowcount
        except Exception as e:
            print(f"SQL执行失败: {e}\nSQL: {sql}\n参数: {params}")
            self.conn.rollback()
            return -1

    def fetchone(self, sql: str, params: Optional[Tuple[Any, ...]] = None) -> Optional[Dict[str, Any]]:
        try:
            with self.conn.cursor() as cursor:
                cursor.execute(sql, params)
                return cursor.fetchone()
        except Exception as e:
            print(f"查询失败: {e}\nSQL: {sql}\n参数: {params}")
            return None

    def fetchall(self, sql: str, params: Optional[Tuple[Any, ...]] = None) -> List[Dict[str, Any]]:
        try:
            with self.conn.cursor() as cursor:
                cursor.execute(sql, params)
                return cursor.fetchall()
        except Exception as e:
            print(f"查询失败: {e}\nSQL: {sql}\n参数: {params}")
            return []

    def __del__(self):
        self.close()
